

#include "gd32f30x_can.h"
#include "can_msg_hdl.h"
#include "BMS_can_msg.h"
#include "can_ringbuff.h"
#include "clean_can_msg.h"
#include "fault_analyse.h"


can_receive_message_struct  can_rec_msg;
can_trasnmit_message_struct can_tar_msg;

STR_CAN_MESSAGE bat_request_frame;
STR_CAN_MESSAGE clean_ctrl_frame;





STR_CAN_BUFFER canmsg_tran_buf = {.length = CAN_MSG_BUFFER_LENGTH};

/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void rec_data_store(can_receive_message_struct *recdata, uint8_t *databuf)
{
	for(uint8_t i=0;i<8;i++)
	{
		*(databuf + i) = recdata->rx_data[i];
	}
}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void tar_data_upload(can_trasnmit_message_struct *tardata, uint8_t *databuf)
{
	for(uint8_t i=0;i<8;i++)
	{
		tardata->tx_data[i] = *(databuf + i);
	}
}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/


void can_mailbox_init(void)
{
	
	BMS_rece_canmailbox_set(CAN_FIFO1);
	clean_rece_canmailbox_set(CAN_FIFO0);
	
	can_interrupt_disable(CAN0, CAN_INT_RFNE0);
	can_interrupt_disable(CAN0, CAN_INT_RFNE1);
	
	nvic_irq_disable(USBD_LP_CAN0_RX0_IRQn);
	nvic_irq_disable(CAN0_RX1_IRQn);
	
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void can_message_init(void)
{
	bat_request_frame.ID = ID_CAN_TAR_BMS_REQ;
	bat_request_frame.ID_type = ID_STANDARD;
	bat_request_frame.length = 8;

	clean_ctrl_frame.ID = ID_CAN_CLEAN_CTRL;
	clean_ctrl_frame.ID_type = ID_EXTENDED;
	clean_ctrl_frame.length = 8;
	
}




/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
void can_FIFO1_data_store(can_receive_message_struct *can_rec_hdl)
{
	switch(can_rec_hdl->rx_efid)
	{
		case ID_CAN_BMS_STATUS:
		{
			rec_data_store(can_rec_hdl, &bmsStatus.raw.data[0]);
			
			bmsStatus.fun_data_analyse();

			break;
		}			
		
		default:
			break;		
	}
	
	switch(can_rec_hdl->rx_sfid)
	{
		case ID_CAN_SER_BMS_STATUS_X1:
		{
			
			rec_data_store(can_rec_hdl, &serBmsStatus.FSM1.data[0]);
			
			serBmsStatus.fsm1_data_analyse();
			
			break;
		}
		
		case ID_CAN_SER_BMS_STATUS_X2:
		{
			rec_data_store(can_rec_hdl, &serBmsStatus.FSM2.data[0]);
			
			serBmsStatus.fsm2_data_analyse();
		
			break;
		}
		
		default:
			break;
	}		
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
void can_FIFO0_data_store(can_receive_message_struct *can_rec_hdl)
{
	
	switch(can_rec_hdl->rx_efid)
	{
		case ID_CAN_CLEAN_FAULT_CODE:
		{		
			rec_data_store(can_rec_hdl, &cleanMsgRec.fault_X1X2.data[0]);
		
			break;
		}
		
		case ID_CAN_CLEAN_SYSTEM:
		{
			rec_data_store(can_rec_hdl, &cleanMsgRec.fault_X3.data[0]);			
			
			break;
		}
		
		case ID_CAN_CLEAN_CURRENT_X1:
		{
			rec_data_store(can_rec_hdl, &cleanMsgRec.fault_X4.data[0]);			
			
			break;
		}
		
		case ID_CAN_CLEAN_CURRENT_X2:
		{
			rec_data_store(can_rec_hdl, &cleanMsgRec.current.data[0]);			
			
			break;
		}
		
		case ID_CAN_CLEAN_RUN_STATUS:
		{
			rec_data_store(can_rec_hdl, &cleanMsgRec.status.data[0]);			
			
			break;
		}

		case ID_CAN_CLEAN_OUTPUT_FSM:
		{
			rec_data_store(can_rec_hdl, &cleanMsgRec.sensor.data[0]);			
			
			break;
		}
	}
	
	cleanMsgRec.rece_cnt++;
	reset_comm_loss_time(ENUM_CLEAN);	
}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void can_rece_msg_analyse(uint8_t fifo_num)
{
	uint8_t length;
	
	length = can_receive_message_length_get(CAN0, fifo_num);
	
	for(uint8_t i=0; i<length; i++)
	{
		
		can_message_receive(CAN0, fifo_num, &can_rec_msg);
		
		if(fifo_num == CAN_FIFO0)
		{
			can_FIFO0_data_store(&can_rec_msg);
		}
		else if(fifo_num == CAN_FIFO1)
		{
			can_FIFO1_data_store(&can_rec_msg);			
		}
	}
}






/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

uint8_t can_tran_boxmail_status(uint32_t can_periph)
{
	uint8_t mailbox_number = 0;
	
	/* select one empty mailbox */
    if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){
        mailbox_number = CAN_MAILBOX0;
    }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){
        mailbox_number = CAN_MAILBOX1;
    }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){
        mailbox_number = CAN_MAILBOX2;
    }else{
        mailbox_number = CAN_NOMAILBOX;
    }
	
	return mailbox_number;
}

/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void can_multiframe_tran(STR_CAN_BUFFER* packetbuf, can_trasnmit_message_struct* tran_msg)
{
	STR_CAN_MESSAGE can_temp;
	
	if(can_tran_boxmail_status(CAN0) != CAN_NOMAILBOX)
	{
		if(can_ringbuf_read(packetbuf, &can_temp))
		{
			if(can_temp.ID_type == ID_STANDARD)
			{
				tran_msg->tx_sfid = can_temp.ID;
				tran_msg->tx_ff = CAN_FF_STANDARD;
			}
			else 
			{
				tran_msg->tx_efid = can_temp.ID;
				tran_msg->tx_ff = CAN_FF_EXTENDED;
			}
			
			tran_msg->tx_dlen = can_temp.length;
			tran_msg->tx_ft = CAN_FT_DATA;
			
			tar_data_upload(tran_msg, &can_temp.data[0]);			
			
			if(tran_msg->tx_dlen != 0)
			{
				can_message_transmit(CAN0, tran_msg);
				tran_msg->tx_dlen = 0;
			}		
		}
	}
}




/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void bms_can_comm_handle(uint16_t runtime_ms)
{	
	static uint16_t bms_req_timing = 0;
	
	bms_req_timing += runtime_ms;
	if(bms_req_timing >= COMM_PERIOD_BMS_REQ)
	{
		bms_req_timing = 0;
		bat_request_frame.data[0] = 1;
		
		can_ringbuf_write(&canmsg_tran_buf, &bat_request_frame);
	}
	
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void clean_can_comm_handle(uint16_t runtime_ms)
{
	static uint16_t clean_ctrl_timing = 0;

	clean_ctrl_timing += runtime_ms;
	if(clean_ctrl_timing >= COMM_PERIOD_CLEAN_CTRL)
	{
		clean_ctrl_timing = 0;
		
		clean_ctrl_msg_store(&clean_ctrl_frame);
		
		can_ringbuf_write(&canmsg_tran_buf, &clean_ctrl_frame);		
	}
}




